home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / cisco / gdpd19jan91.shar / gdpd-hp.c next >
Encoding:
C/C++ Source or Header  |  1992-08-07  |  18.0 KB  |  868 lines

  1. /*
  2.  * Gateway Discovery Protocol daemon suitable for using on Un*x systems.
  3.  *
  4.  * September 1989, Greg Satz
  5.  *
  6.  * Copyright (c) 1989 by cisco Systems, Inc.
  7.  * All rights reserved.
  8.  */
  9.  
  10. #include <sys/types.h>
  11. #include <sys/socket.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/file.h>
  14. #include <sys/mbuf.h>
  15.  
  16. #ifdef FD_SETSIZE
  17. #define getdtablesize() FD_SETSIZE
  18. #endif 
  19.  
  20. #include <net/if.h>
  21. #include <net/route.h>
  22. #include <netinet/in.h>
  23. #include <netinet/if_ether.h>
  24. #include <netinet/arp.h>
  25.  
  26. /* required for HP vna_table processing  */
  27. #include <net/probe_gdp.h> 
  28. #include <net/raw8023.h>
  29. #include <net/lan_802.h> 
  30. #include <netinet/probe_2.h>
  31. #include <fcntl.h> 
  32. #include <memory.h> 
  33.  
  34. #include <stdio.h>
  35. #include <signal.h>
  36. #include <errno.h>
  37. #include <netdb.h>
  38. #include <syslog.h>
  39. #include <nlist.h>
  40.  
  41. /*
  42.  * Gateway Discovery Protocol definitions
  43.  */
  44.  
  45. #define    GDP_VERSION    1
  46.  
  47. /*
  48.  * Operations
  49.  */
  50.  
  51. #define    GDP_REPORT    1
  52. #define    GDP_QUERY    2
  53.  
  54. /*
  55.  * GDP listener port
  56.  */
  57.  
  58. #define    GDP_PORT    1997
  59.  
  60. /*
  61.  * GDP packet format
  62.  */
  63.  
  64. struct gdppkt {
  65.     unsigned char version;
  66.     unsigned char code;
  67.     unsigned char count;
  68.     unsigned char reserved;
  69.     struct addrgrp {
  70.     struct in_addr ip;
  71.     unsigned short priority;
  72.     unsigned short holdtime;
  73.     } addrs[1];
  74. };
  75.  
  76. #define    ALARM_INTERVAL        1
  77.  
  78. #define TIOCNOTTY       _IO('t', 113)           /* void tty association */
  79.  
  80. #define    KERNEL        "/hp-ux"
  81. #define    MEM        "/dev/kmem"
  82.  
  83. struct nlist nl[] = {
  84. #define    X_PR_VNATAB    0
  85.     { "_pr_vnatab" },
  86. #define    N_RTHOST    1
  87.     { "_rthost" },
  88. #define    N_RTNET        2
  89.     { "_rtnet" },
  90. #define    X_SPACE        3
  91.         { " " },
  92.     { "" },
  93. };
  94.  
  95. struct iface {
  96.     char name[IFNAMSIZ];
  97.     short flags;
  98.     struct in_addr ipaddress;
  99.     struct in_addr ipmask;
  100.     struct in_addr ipbroadcast;
  101.     struct iface *next;
  102. } *iflist;
  103.  
  104. struct neighbor {
  105.     struct in_addr ip;
  106.     unsigned short priority;
  107.     unsigned short holdtime;
  108.     struct neighbor *next;
  109. };
  110.  
  111. struct neighbor *rcvd_neighbors;
  112. struct neighbor *sent_neighbors;
  113.  
  114. struct neighbor *default_neighbor;
  115.  
  116. #define    DEFAULT_PRIORITY    100
  117. #define    DEFAULT_HOLDTIME    15
  118.  
  119. int debug;                /* debugging flag */
  120. int flush;                /* flush routing table flag */
  121. int logging;                /* syslog logging flag */
  122. int hold_time;                /* tell others how often to hold */
  123. int metric;                /* how do we run */
  124. int priority;                /* what priority do we advertise */
  125. int query_time;                /* how often to send queries */
  126. int query;
  127. int report_time;            /* how often to send reports */
  128. int report;
  129. int round_robin;            /* how often to cycle parallel gws */
  130. int round;
  131.  
  132. int m;
  133. int s;
  134. struct sockaddr_in from;
  135. int fromlen;
  136. struct hostent *hp;
  137. struct servent *sp;
  138. unsigned char buf[BUFSIZ];
  139.  
  140. int timer();
  141.  
  142. /*
  143.  * main
  144.  * Perform GDP processing depending on what we were told
  145.  */
  146.  
  147. main (argc, argv)
  148.     int argc;
  149.     char *argv;
  150. {
  151.     int c, status, on = 1;
  152.     struct gdppkt *gdp;
  153.     struct addrgrp ag;
  154.     struct in_addr bip;
  155.     extern int errno;
  156.     extern char *optarg;
  157.     extern int optind;
  158.  
  159.     debug = 0;
  160.     flush = 0;
  161.     logging = 0;
  162.     metric = 1;                /* default to one hop */
  163.     priority = DEFAULT_PRIORITY;
  164.     hold_time = DEFAULT_HOLDTIME;
  165.     query_time = 0;
  166.     report_time = 0;
  167.     round_robin = 0;
  168.     iflist = NULL;
  169.     rcvd_neighbors = NULL;
  170.     sent_neighbors = NULL;
  171.     default_neighbor = NULL;
  172.     bip.s_addr = 0L;
  173. #ifdef LOG_DAEMON
  174.     openlog("gdpd", LOG_PID, LOG_DAEMON);
  175. #else
  176.     openlog("gdpd", LOG_PID);
  177. #endif
  178.     while ((c = getopt(argc, argv, "dfh:lm:p:q:r:t:")) != EOF)
  179.     switch (c) {
  180.     case 'd':            /* debug */
  181.         debug = 1;
  182.         break;
  183.     case 'f':            /* flush  */
  184.         flush = 1;
  185.         break;
  186.     case 'h':            /* hold time */
  187.         hold_time = atoi(optarg);
  188.         if (hold_time < 0) {
  189.         syslog(LOG_INFO, "%s: illegal hold time value - %d",
  190.             argv[0], hold_time);
  191.         exit(1);
  192.         }
  193.         break;
  194.     case 'l':            /* logging */
  195.         logging = 1;
  196.         break;
  197.     case 'm':            /* metric */
  198.         metric = atoi(optarg);
  199.         if (metric < 0) {
  200.         syslog(LOG_INFO, "%s: illegal metric value - %d",
  201.             argv[0], metric);
  202.         exit(1);
  203.         }
  204.         break;
  205.     case 'p':            /* priority */
  206.         priority = atoi(optarg);
  207.         if (priority < 0) {
  208.         syslog(LOG_INFO, "%s: illegal priority value - %d",
  209.             argv[0], priority);
  210.         exit(1);
  211.         }
  212.         break;
  213.     case 'q':            /* query */
  214.         query_time = atoi(optarg);
  215.         if (query_time < 0) {
  216.         syslog(LOG_INFO, "%s: illegal querying value - %d",
  217.             argv[0], query_time);
  218.         exit(1);
  219.         }
  220.         break;
  221.     case 'r':            /* report */
  222.         report_time = atoi(optarg);
  223.         if (report_time < 0) {
  224.         syslog(LOG_INFO, "%s: illegal reporting value - %d",
  225.             argv[0], report_time);
  226.         exit(1);
  227.         }
  228.         break;
  229.     case 't':            /* time */
  230.         round_robin = atoi(optarg);
  231.         if (round_robin < 0) {
  232.         syslog(LOG_INFO, "%s: illegal round robin value - %d",
  233.             argv[0], round_robin);
  234.         exit(1);
  235.         }
  236.         round_robin *= 60;        /* make seconds */
  237.         break;
  238.     default:
  239.         syslog(LOG_INFO, "%s: illegal switch -%s", argv[0], optarg);
  240.         exit(1);
  241.     }
  242.  
  243.     if (query_time != 0 && report_time != 0) {
  244.     syslog(LOG_INFO, "%s: cannot report and query simultaneously.\n",
  245.         argv[0]);
  246.     exit(1);
  247.     }
  248.     bzero(&ag, sizeof(struct addrgrp));
  249.     while (argc != optind) {
  250.     ag.ip.s_addr = inet_addr(argv[optind]);
  251.     if (ag.ip.s_addr == -1) {
  252.         hp = gethostbyname(argv[optind]);
  253.         if (hp == NULL) {
  254.         syslog(LOG_INFO, "%s: %s: unknown host\n", argv[0],
  255.             argv[optind]);
  256.         exit(1);
  257.         }
  258.         bcopy(hp->h_addr, &ag.ip, sizeof(ag.ip));
  259.     }
  260.     enter_neighbor(&sent_neighbors, &ag);
  261.     optind++;
  262.     }
  263.     query = query_time;
  264.     report = report_time;
  265.     round = round_robin;
  266.     if (!debug) {
  267.         status = fork();
  268.     if (fork() != 0) { 
  269.             syslog(LOG_ERR, " %i, fork kills the parent",status);
  270.         exit(0);
  271.         }
  272.     for (c = 0; c < getdtablesize(); c++) {    
  273.         (void) close(c);
  274.         }    
  275.     (void) open("/", O_RDONLY);
  276.     (void) dup2(0, 1);
  277.     (void) dup2(0, 2);
  278.     c = open("/dev/tty", O_RDWR);
  279.     if (c >= 0) {
  280.         ioctl(c, TIOCNOTTY, (char *)0);
  281.         (void) close(c);
  282.     } 
  283.  
  284.     if (metric == 0 || flush) {
  285.     nlist(KERNEL, nl);
  286.     if (nl[X_PR_VNATAB].n_value == 0) {
  287.             syslog(LOG_INFO," failed vnatab nlist ");
  288.     }
  289.     if (nl[N_RTHOST].n_value == 0) {
  290.             syslog(LOG_INFO," failed rthost nlist ");
  291.         exit(1);
  292.     }
  293.     if (nl[N_RTNET].n_value == 0) {
  294.             syslog(LOG_INFO," failed rtnet nlist ");
  295.         exit(1);
  296.     }
  297.     m = open(MEM, O_RDONLY);
  298.     if (m < 0) {
  299.         exit(1);
  300.     }
  301.     }
  302.     if (debug)
  303.     syslog(LOG_DEBUG, "server starting");
  304.  
  305. #ifdef LOG_DAEMON
  306.     openlog("gdpd", LOG_PID, LOG_DAEMON);
  307. #else
  308.     openlog("gdpd", LOG_PID);
  309. #endif
  310.     }
  311.  
  312.     /*
  313.      * Getgetd listener socket
  314.      */
  315.     if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  316.     syslog(LOG_ERR, "socket: %m");
  317.     exit(1);
  318.     }
  319.  
  320. #ifdef SO_BROADCAST
  321.     if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
  322.     syslog(LOG_ERR, "setsockopt: %m");
  323.     exit(1);
  324.     }
  325. #endif
  326.  
  327.     /*
  328.      * Get port we need to pay attention to
  329.      */
  330.     bzero((caddr_t)&from, sizeof(from));
  331.     from.sin_family = AF_INET;
  332.     from.sin_addr.s_addr = INADDR_ANY;
  333.     sp = getservbyname("gdp", "udp");
  334.     if (sp == NULL)
  335.     from.sin_port = htons(GDP_PORT);
  336.     else
  337.     from.sin_port = htons(sp->s_port);
  338.  
  339.     if (bind(s, &from, sizeof(from)) < 0) {
  340.     syslog(LOG_ERR, "bind: %m");;
  341.     exit(1);
  342.     }
  343.  
  344.     build_iflist();
  345.     send_query(bip);
  346.     signal(SIGALRM, timer);
  347.     timer();
  348.  
  349.     /*
  350.      * Now do the work
  351.      */
  352.  
  353.     for (;;) {
  354.        syslog(LOG_ERR, "in for loop");
  355.     fromlen = sizeof(from);
  356.     c = recvfrom(s, buf, sizeof(buf), 0, (caddr_t)&from, &fromlen);
  357.     if (c <= 0) {
  358.         if (errno == EINTR)
  359.         continue;
  360.         syslog(LOG_ERR, "recvfrom: %m");
  361.         exit(1);
  362.     }
  363.     gdp = (struct gdppkt *)buf;
  364.     if (gdp->version != GDP_VERSION)
  365.         continue;
  366.     if (debug) {
  367.         hp = gethostbyaddr(&from.sin_addr, sizeof(struct in_addr),
  368.         AF_INET);
  369.         syslog(LOG_DEBUG, "%s received from %s", (gdp->code == GDP_REPORT
  370.         ? "REPORT" : (gdp->code == GDP_QUERY ? "QUERY" : "UNKNOWN")),
  371.         hp ? hp->h_name : (char *)inet_ntoa(from.sin_addr));
  372.     }
  373.     switch (gdp->code) {
  374.     case GDP_REPORT:
  375.         if (report_time == 0)
  376.         process_report(&from, gdp);
  377.         break;
  378.     case GDP_QUERY:
  379.         if (report_time != 0)
  380.         process_query(&from, gdp);
  381.         break;
  382.     default:
  383.         break;
  384.     }
  385.     }
  386. }
  387.  
  388. /*
  389.  * find_neighbor
  390.  * Look for a given neighbor in the list and return ptr or NULL
  391.  */
  392.  
  393. struct neighbor *find_neighbor (nt, ip)
  394.     struct neighbor **nt;
  395.     struct in_addr ip;
  396. {
  397.     struct neighbor *p;
  398.  
  399.     for (p = *nt; p != NULL; p = p->next)
  400.     if (p->ip.s_addr == ip.s_addr)
  401.         break;
  402.     return(p);
  403. }
  404.  
  405. /*
  406.  * enter_neighbor
  407.  * Enter a new neighbor into the table in priority order
  408.  */
  409.  
  410. enter_neighbor (nt, ag)
  411.     struct neighbor **nt;
  412.     struct addrgrp *ag;
  413. {
  414.     struct neighbor *p, *pp, *newp;
  415.  
  416.     newp = (struct neighbor *)malloc(sizeof(struct neighbor));
  417.     if (newp == NULL)
  418.     return;
  419.  
  420.     newp->ip = ag->ip;
  421.     newp->priority = ag->priority;
  422.     newp->holdtime = ag->holdtime;
  423.     newp->next = NULL;
  424.     for (p = pp = *nt; p != NULL; pp = p, p = p->next)
  425.     if (p->priority >= newp->priority)
  426.         continue;
  427.     if (p == NULL) {
  428.     if (*nt == NULL)
  429.         *nt = newp;
  430.     else
  431.         pp->next = newp;
  432.     } else if (p == pp) {
  433.     newp->next = *nt;
  434.     *nt = newp;
  435.     } else {
  436.     pp->next = newp;
  437.     newp->next = p;
  438.     }
  439. }
  440.  
  441. /*
  442.  * delete_neighbor
  443.  * Remove neighbor from the list
  444.  */
  445.  
  446. delete_neighbor (nt, dp)
  447.     struct neighbor **nt;
  448.     struct neighbor *dp;
  449. {
  450.     struct neighbor *p, *pp;
  451.  
  452.     for (p = pp = *nt; p != NULL; pp = p, p = p->next)
  453.     if (p == dp)
  454.         break;
  455.     if (p == pp)
  456.     *nt = p->next;
  457.     else
  458.     pp->next = p->next;
  459.     free(p);
  460.  
  461. }
  462.  
  463. /*
  464.  * robin_neighbor
  465.  * Perform round robin on received neighbors of equal priority
  466.  */
  467.  
  468. robin_neighbor ()
  469. {
  470.     struct neighbor *p, *pp;
  471.  
  472.     /*
  473.      * Find where next lower priorty starts
  474.      */
  475.     for (p = pp = rcvd_neighbors; p != NULL; p = p->next)
  476.     if (default_neighbor->priority > p->priority)
  477.         break;
  478.     /*
  479.      * If there is only a single entry, then don't bother
  480.      */
  481.     if (default_neighbor == pp)
  482.     return;
  483.  
  484.     /*
  485.      * Splice old one at end of equal priority list
  486.      */
  487.     rcvd_neighbors = default_neighbor->next;
  488.     pp->next = default_neighbor;
  489.     default_neighbor->next = p;
  490.     update_routes();
  491. }
  492.  
  493. /*
  494.  * process_report
  495.  * handle processing of GDP report messages
  496.  */
  497.  
  498. process_report (from, gdp)
  499.     struct sockaddr_in *from;
  500.     struct gdppkt *gdp;
  501. {
  502.     struct neighbor *p;
  503.     struct addrgrp *a;
  504.  
  505.     a = gdp->addrs;
  506.     while (gdp->count-- > 0) {
  507.     if (valid_address(a->ip)) {
  508.         p = find_neighbor(&sent_neighbors, a->ip);
  509.         if (p != NULL)
  510.         p->holdtime = a->holdtime;
  511.         p = find_neighbor(&rcvd_neighbors, a->ip);
  512.         if (p == NULL || p->priority != a->priority) {
  513.         if (p != NULL) {
  514.             if (flush) {
  515.                         flush_routes(p->ip);
  516.                     }
  517.             delete_neighbor(&rcvd_neighbors, p);
  518.         }
  519.         enter_neighbor(&rcvd_neighbors, a);
  520.         update_routes();
  521.         round = round_robin;        /* restart timer */
  522.         } else
  523.         p->holdtime = a->holdtime;
  524.     } else if (debug)
  525.         syslog(LOG_DEBUG, "invalid IP address: %s",
  526.         inet_ntoa(a->ip));
  527.     a++;
  528.     }
  529. }
  530.  
  531. /*
  532.  * process_query
  533.  * Process a QUERY and return a REPORT
  534.  */
  535.  
  536. process_query (from, gdp)
  537.     struct sockaddr_in *from;
  538.     struct gdppkt *gdp;
  539. {
  540. }
  541.  
  542. /*
  543.  * timer
  544.  * Wake up once in a while and process running timers, etc.
  545.  */
  546.  
  547. timer ()
  548. {
  549.     struct neighbor *p, *dp;
  550.     struct in_addr bip;
  551.  
  552.     bip.s_addr = 0L;
  553.     if (report_time != 0) {
  554.     if (report <= 0) {
  555.         send_report(bip);
  556.         report = report_time;
  557.     } else
  558.         report -= ALARM_INTERVAL;
  559.     } else {
  560.     if (query_time != 0) {
  561.         query -= ALARM_INTERVAL;
  562.         if (query <= 0) {
  563.         for (p = sent_neighbors; p != NULL; p = p->next)
  564.             send_query(p->ip);
  565.         query = query_time;
  566.         }
  567.     }
  568.     for (p = rcvd_neighbors; p != NULL; ) {
  569.         dp = p;
  570.         p = p->next;
  571.         dp->holdtime -= ALARM_INTERVAL;
  572.         if (dp->holdtime <= 0) {
  573.         if (flush) {
  574.             flush_routes(dp->ip); 
  575.                 }
  576.             delete_neighbor(&rcvd_neighbors, dp);
  577.         update_routes();
  578.         round = round_robin;        /* restart timer */
  579.         }
  580.     }
  581.     }
  582.     if (round_robin != 0) {
  583.     round -= ALARM_INTERVAL;
  584.     if (round <= 0) {
  585.         if (default_neighbor != NULL)
  586.         robin_neighbor();
  587.         round = round_robin;
  588.     }
  589.     }
  590.     alarm(ALARM_INTERVAL);
  591. }
  592.  
  593. /*
  594.  * send_query
  595.  * Send a GDP query message
  596.  */
  597.  
  598. send_query (ip)
  599.     struct in_addr ip;
  600. {
  601.     struct gdppkt gdp;
  602.     struct sockaddr_in sin;
  603.     struct iface *ifp;
  604.     struct neighbor *p;
  605.  
  606.     bzero(&gdp, sizeof(gdp));
  607.     gdp.version = GDP_VERSION;
  608.     gdp.code = GDP_QUERY;
  609.     bzero(&sin, sizeof(sin));
  610.     sin.sin_family = AF_INET;
  611.     sin.sin_addr = ip;
  612.     if (sp == NULL)
  613.     sin.sin_port = htons(GDP_PORT);
  614.     else
  615.     sin.sin_port = htons(sp->s_port);
  616.     if (ip.s_addr == 0L) {
  617.     for (ifp = iflist; ifp != NULL; ifp = ifp->next) {
  618.         if ((ifp->flags & IFF_BROADCAST) == 0)
  619.         continue;
  620.         sin.sin_addr = ifp->ipbroadcast;
  621.         (void) sendto(s, &gdp, sizeof(gdp) - sizeof(struct addrgrp), 0,
  622.         &sin, sizeof(sin));
  623.     }
  624.     for (p = sent_neighbors; p != NULL; p = p->next)
  625.         send_query(p->ip);
  626.     } else
  627.     (void) sendto(s, &gdp, sizeof(gdp) - sizeof(struct addrgrp), 0,
  628.         &sin, sizeof(sin));
  629. }
  630.  
  631. /*
  632.  * send_report
  633.  * Send a GDP REPORT message
  634.  */
  635.  
  636. send_report (ip)
  637.     struct in_addr ip;
  638. {
  639. }
  640.  
  641. /*
  642.  * build_iflist
  643.  * Build a list of interfaces and accompaning information
  644.  */
  645.  
  646. build_iflist ()
  647. {
  648.     int n;
  649.     char ifbuf[BUFSIZ];
  650.     struct ifconf ifc;
  651.     struct ifreq *ifr, ifreq;
  652.     struct iface *ifp;
  653.     struct sockaddr_in *sa;
  654.     short flags;
  655.  
  656.     ifc.ifc_len = sizeof(ifbuf);
  657.     ifc.ifc_buf = ifbuf;
  658.     if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
  659.     syslog(LOG_ERR, "ioctl(IFCONF): %m");
  660.     exit(1);
  661.     }
  662.     ifr = ifc.ifc_req;
  663.     for (n = ifc.ifc_len / sizeof(struct ifreq); n > 0; n--, ifr++) {
  664.     /*
  665.      * Ignore the loopback interface
  666.      */
  667.     if (strncmp(ifr->ifr_name, "lo", 2) == 0)
  668.         continue;
  669.     /*
  670.      * Ignore all interfaces which aren't running
  671.      */
  672.     strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name));
  673.     if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0)
  674.         continue;
  675.     else
  676.         flags = ifreq.ifr_flags;
  677.     if ((flags & IFF_RUNNING) == 0)
  678.         continue;
  679.     sa = (struct sockaddr_in *)&ifr->ifr_addr;
  680.     /*
  681.      * Ignore 0.0.0.0
  682.      */
  683.     if (sa->sin_addr.s_addr == 0L)
  684.         continue;
  685.     ifp = (struct iface *)malloc(sizeof(struct iface));
  686.     if (ifp == NULL)
  687.         break;
  688.     bzero(ifp, sizeof(struct iface));
  689.     strncpy(ifp->name, ifr->ifr_name, sizeof(ifp->name));
  690.     ifp->ipaddress = sa->sin_addr;
  691.     ifp->flags = flags;
  692.     strncpy(ifreq.ifr_name, ifp->name, sizeof(ifp->name));
  693.     if (ioctl(s, SIOCGIFNETMASK, &ifreq) >= 0) {
  694.         sa = (struct sockaddr_in *)&ifreq.ifr_addr;
  695.         ifp->ipmask = sa->sin_addr;
  696.     }
  697.     if (ifp->flags & IFF_BROADCAST) {
  698.         strncpy(ifreq.ifr_name, ifp->name, sizeof(ifp->name));
  699.         if (ioctl(s, SIOCGIFBRDADDR, &ifreq) >= 0) {
  700.         sa = (struct sockaddr_in *)&ifreq.ifr_addr;
  701.         ifp->ipbroadcast = sa->sin_addr;
  702.         }
  703.     }
  704.     if (iflist == NULL)
  705.         iflist = ifp;
  706.     else {
  707.         ifp->next = iflist;
  708.         iflist = ifp;
  709.     }
  710.     }
  711. }
  712.  
  713. /*
  714.  * valid_address
  715.  * Determine if give IP address is something we grok.
  716.  */
  717.  
  718. valid_address (ip)
  719.     struct in_addr ip;
  720. {
  721.     struct iface *ifp;
  722.  
  723.     for (ifp = iflist; ifp != NULL; ifp = ifp->next) {
  724.     if ((ip.s_addr & ifp->ipmask.s_addr) ==
  725.         (ifp->ipaddress.s_addr & ifp->ipmask.s_addr))
  726.         return(1);
  727.     }
  728.     return(0);
  729. }
  730.  
  731. /*
  732.  * update_routes
  733.  * Update default route if necessary when something changes
  734.  */
  735.  
  736. update_routes ()
  737. {
  738.     struct rtentry rt;
  739.     struct sockaddr_in *sa;
  740.     struct in_addr inet_makeaddr();
  741.  
  742.     if (default_neighbor == rcvd_neighbors)
  743.     return;
  744.  
  745.     bzero(&rt, sizeof(rt));
  746.     rt.rt_flags = RTF_UP;
  747.     if (metric > 0)
  748.     rt.rt_flags |= RTF_GATEWAY;
  749.     sa = (struct sockaddr_in *)&rt.rt_dst;
  750.     sa->sin_family = AF_INET;
  751.     sa->sin_addr = inet_makeaddr(0, INADDR_ANY);
  752.     sa = (struct sockaddr_in *)&rt.rt_gateway;
  753.     sa->sin_family = AF_INET;
  754.     if (default_neighbor != NULL) {
  755.     sa->sin_addr = default_neighbor->ip;
  756.     if (metric == 0)
  757.         flush_vna();
  758.     if (logging)
  759.         syslog(LOG_INFO, "deleting old default: %s",
  760.         inet_ntoa(sa->sin_addr));
  761.     if (!debug)
  762.         (void) ioctl(s, SIOCDELRT, &rt);
  763.     }
  764.     default_neighbor = rcvd_neighbors;
  765.     if (default_neighbor == NULL)
  766.     return;
  767.     sa->sin_addr = default_neighbor->ip;
  768.     if (logging)
  769.     syslog(LOG_INFO, "adding new default: %s",
  770.         inet_ntoa(sa->sin_addr));
  771.     if (!debug)
  772.     (void) ioctl(s, SIOCADDRT, &rt);
  773. }
  774.  
  775.  
  776. /*
  777.  * flush_routes
  778.  * Flush the routing table. We do this when asked.
  779.  */
  780.  
  781. flush_routes (ip)
  782.     struct in_addr ip;
  783. {
  784.     struct in_addr in;
  785.     struct mbuf mb;
  786.     register struct rtentry *rt;
  787.     register struct mbuf *mbp;
  788.     struct mbuf **routehash;
  789.     int rthashsize, i, doinghost = 1;
  790.  
  791.     if (logging)
  792.     syslog(LOG_INFO, "flushing routes via %s", inet_ntoa(ip));
  793.     lseek(m, nl[X_SPACE].n_value, 0);
  794.     read(m, &rthashsize, sizeof (rthashsize));
  795.     routehash = (struct mbuf **)malloc(rthashsize*sizeof (struct mbuf *));
  796.     lseek(m, nl[N_RTHOST].n_value, 0);
  797.     read(m, routehash, rthashsize*sizeof (struct mbuf *));
  798. again:
  799.     for (i = 0; i < rthashsize; i++) {
  800.         syslog(LOG_INFO, "entered again ");
  801.     if (routehash[i] == 0)
  802.         continue;
  803.        syslog(LOG_INFO, "passed again ");
  804.     mbp = routehash[i];
  805.         while (mbp) {
  806.         lseek(m, mbp, 0);
  807.         read(m, &mb, sizeof (mb));
  808.         rt = mtod(&mb, struct rtentry *);
  809.         if ((rt->rt_flags & RTF_GATEWAY) &&
  810.             rt->rt_gateway.sa_family == AF_INET) {
  811.             in = ((struct sockaddr_in *)&rt->rt_gateway)->sin_addr;
  812.             if (in.s_addr == ip.s_addr) {
  813.             if (logging) {
  814.                 in = ((struct sockaddr_in *)&rt->rt_dst)->sin_addr
  815. ;
  816.                 syslog(LOG_INFO, "flushing route %s",
  817.                 inet_ntoa(in));
  818.             }
  819.             if (!debug)
  820.                 (void) ioctl(s, SIOCDELRT, (caddr_t)rt);
  821.             }
  822.         }
  823.         mbp = mb.m_next;
  824.         }
  825.     }
  826.     if (doinghost) {
  827.     lseek(m, nl[N_RTNET].n_value, 0);
  828.     read(m, routehash, rthashsize*sizeof (struct mbuf *));
  829.     doinghost = 0;
  830.     goto again;
  831.     }
  832.     free(routehash);
  833. }
  834.  
  835. flush_vna()
  836.  
  837. {
  838.  
  839. int n, status;
  840.  
  841. extern int errno;
  842.  
  843. struct vnatab pr_vnatab[VNATAB_SIZE];
  844.  
  845. struct vnatab vna_entry;
  846.  
  847. syslog(LOG_ERR,"flushing vnatab");
  848.  
  849. n = open(MEM,O_RDWR);
  850.  
  851. if (n == -1) {
  852.     syslog(LOG_ERR,"%i, mem open failed",errno);
  853.     exit(1);
  854.     }
  855.  
  856. (void) memset(pr_vnatab, 0, sizeof(pr_vnatab));
  857.  
  858. status =  (lseek(n, (long) nl[X_PR_VNATAB].n_value, 0));
  859. if  (status == -1) {
  860.     syslog(LOG_ERR,"%i, lseek failed",errno);
  861.     exit(1);
  862.    }    
  863.  
  864. (void) write(n, pr_vnatab, sizeof(pr_vnatab));
  865. (void) close(n);
  866.  
  867. }
  868.